// $Id: ajaxrequest.js

// @file: Provides some function for ajax communication with the server. The request event can be attached to form submit or to a link click.
//    This code is copied from sponsor_advanced.js, from sponsor_advanced module.

//  TO DO: replace sponsor_advanced.js with this file.

if (Drupal.jsEnabled){
	//variable used with ajaxLink to store a cache of loaded pages.
	var pages_cache = new Array();
	
	//meta information about the cache. It is the "data" parameter sent to ajaxLink.
	var caches_meta = new Array();
	
	//an array that, for each container, store the type of the value that is currently shown:
	//1: initial value.
	//2: initial value, but assigned by javascript.
	//3: value from an ajax request.
	var container_values = new Array();
	
	//Attach a submit event to a form. The response from the server should be a JSON object with the following parameters:
	// - status ('error' or 'success');
	// - messages (the messages that have to be rendered)
	// - messages_location (optional parameter. If it is specified, it is the id of the element in which the messages will appear, at the top of it)
	// - body (the body of the response)
	// - location_id (the id of the element that would be replaced with the content in the body)
	// - redirect (an url where to redirect. If this is specified, no other operations are performed)
	
	//@param: init_function: a callback that will be called for initialization purposes, after the response data is embeded in the html code.
	//@param: parameters: an object that will be passed to the init function.
	function attachSubmitEvent(form, init_function, init_parameters){
		var form_id = $(form).attr("id");
		$(form).unbind('submit').bind('submit', function(event){
			var options = {
				dataType: 'json',
				success: function(data){
					//remove any elements with the id of the form.
					$(form).remove();
					responseHandler(data, init_function, init_parameters);
				}
			}
			//remove any status messages that exists on the page.
			$('#messages').parent().remove();
			//remove any ajax loader.
			$('#pager_ajax_loader').remove();
			$("#"+form_id).before(Drupal.settings.thickbox.ajax_loader);
			$(form).slideUp();
			$(this).ajaxSubmit(options);
			return false;
		});
	}
	
	// Same scope as attachSubmitEvent, but in this case, the trigger is the user clicking an element, not a form submit
	// The "container" parameter is the DOM element that will be "slided up" the user clicks the element
	// The "url" parameter is the url that will be called.
	// If the "confirm_text" parameter is provided, a confirm form is shown before any action will take place
	// if the "hide_loader" parameter is specified (for example is 1),then the ajax loader is not shown.
	function attachClickEvent(element, container, url, init_function, confirm_text, init_parameters, hide_loader){
		$(element).unbind().bind("click", function(event){
			if (confirm_text){
				var ok = confirm(confirm_text);
				if (ok == false){
					return false;
				}
			}
			//remove any status messages that exists on the page.
			$('#messages').parent().remove();
			//remove any ajax loader.
			$('#pager_ajax_loader').remove();
			if (container){
				$(container).slideUp(function(){
					if (!hide_loader){
						$(container).after(Drupal.settings.thickbox.ajax_loader);
					}
					$(container).remove();					
				});
			} else {
				if (!hide_loader){
					$(this).after(Drupal.settings.thickbox.ajax_loader);
				}
			} 
			$.getJSON(url, function(data){
				responseHandler(data, init_function, init_parameters);
			});
			return false;
		});
	}
	
	function responseHandler(data, init_function, init_parameters){
		if (data.status == 'success'){
			//if this parameter is specified, no other actions are performed.
			if (data.redirect){
				window.location.href = data.redirect;
			}
			//remove any ajax loader.
			$('#pager_ajax_loader').remove();
			//show the body
			if (data.location_id){
				$("#"+data.location_id).hide().html(data.body).fadeTo(1500, 1);
			} else {
				$("body").append(data.body);
			}
			//show the messages
			if (data.messages){
				if (data.messages_location){
					$('#'+data.messages_location).prepend(data.messages);
				} else {
					$('#header').after(data.messages);
				}
			}
			//call the init function if is defined.
			if (init_function){
				if (init_parameters){
					init_function(init_parameters);
				} else {
					init_function();
				}
			}
			//show and hide the textxs with js.
			if (window.show_divs){
				show_divs();
			}
			if (window.hide_divs){
				hide_divs();
			}
		}
	}
	
	function hash_link(link, container_id){
		var output = '';
		if (link){
			output += link;
		}
		if (container_id){
			output += container_id;
		}
		output += output.replace(/^.*#/, '');
		if (window.sha1Hash){
			output = sha1Hash(output);
		}
		return output;
	}
	
	//Transforms a simple link into a link that get the results with AJAX.
	//The data is an object with the following fields:
	// - element: the DOM element on which the event is assigned (usually a link). It is required.
	// - container: the DOM element that will be used for the output of the request. It is optional.
	// - loader: a loader that will be shown during the request. It is optional.
	// - init_function: a function that will be called after the request has been made and the response has been received. It is optional.
	// - init_parameters: the parameters that will be used to call the function. If there are more than one parameter, the approach is to
	//                    encapsulate them into an object and pass the object as the only paramater.
	// - smart: if this is specified to "none" then the smart functionality is not active. The "smart" feature:
	        //  - after a request for a page is made, its content is cached so that if the user clicks again on that page, the request is not made again
	        //    for that page. For example: user is on page 1 -> clicks on page 2 -> clicks on page 3 -> clicks on page 2 => the content for page 2
	        //    is retrieved from the cache. The cache is actually an javascript array, with the keys representing the link's href attribute.
	function ajaxLink(data){
		if (data.element){
			if (data.smart != 'none'){
				caches_meta[$(data.container).attr('id')] = data;
				if (!pages_cache['initial_value']){
					pages_cache['initial_value'] = new Array();
				}
				if (!pages_cache['initial_value'][$(data.container).attr('id')]){
					pages_cache['initial_value'][$(data.container).attr('id')] = $(data.container).html();
				}
				if (!container_values[$(data.container).attr('id')]){
					container_values[$(data.container).attr('id')] = 1;
				}
			}
			$(data.element).unbind().bind('click', function(event){
				var href = $(this).attr('href');
				var clean_href = hash_link(href, $(data.container).attr('id'));
				//show the ajax loader
				if (data.loader){
					$(data.loader).show();
				}
				var data_exists = 0;
				//if the smart feature is not specified to be inactive, then it's active by default and tries to see if there is already a cached data.
				if (data.smart != 'none'){
					if (pages_cache[clean_href] && pages_cache[clean_href][$(data.container).attr('id')]){
						data_exists = 1;
						show_response(pages_cache[clean_href][$(data.container).attr('id')]);
					}
				}
				
				if (!data_exists){
					//perform the ajax request and show the results.
					$.get(data.element.href, show_response);
				}
				
				function show_response(response_data){
					//first update the cache.
					if (data.smart != 'none'){
						if (!pages_cache[clean_href]){
							pages_cache[clean_href] = new Array();
						}
						pages_cache[clean_href][$(data.container).attr('id')] = response_data;
						container_values[$(data.container).attr('id')] = 3;
						//for all containers that were not yet populated with other values, but only with the initial value,
						//assign the initial value also for this hash.
						for (container_value_id in container_values){
							if (container_values[container_value_id] != 3 && caches_meta[container_value_id]){
								//update the type of the value, so that we know that this value was assigne with js.
								container_values[container_value_id] == 2;
								pages_cache[clean_href][container_value_id] = $(caches_meta[container_value_id].container).html();
							}
						}
					}
					show_data_on_page(response_data, data);
				}
				$.history.load(clean_href);
				return false;
			});
		}
	}
	
	// Adds an ajax pager functionality on the specified container id.
	//The data is an object with the following fields:
	// - container_id: the id of the container that holds the content and the pager.
	// - init_function: the name of the function to be called after the data from the request is rendered. If it is now specified, then
	//   the default is to call ajaxPager for initialization. IMPORTANT: if it is specified, the initialization function should call
	//   again the ajaxPager, if the response from the server also contains the pager.
	// - init_parameters: parameters used when the initialization function is called.
	// - smart: @see ajaxLink for a detailed explanation.
	function ajaxPager(data){
		if (data.container_id){
			$("#"+data.container_id+" div.div-pager-links a").each(function(){
				//add the container id to the link, so that the server script will know when to abort the further execution of the script.
				//For example: if the container is "projects_view", then the server script will exit imediately after it will print the results
				//for this container.
				if (!this.href.match(/container=/i)){
					if (this.href.match(/page=/i)){
						this.href = this.href+"&container="+data.container_id;
					} else {
						this.href = this.href+"?container="+data.container_id;
					}
				}
				if (!data.init_function){
					data.init_function = ajaxPager;
					data.init_parameters = data;
				}
				$("#"+data.container_id+" div.div-pager-links a").each(function(){
					ajaxLink({
						element: this,
						container: $("#"+data.container_id).get(0),
						loader: $("#"+data.container_id+" .div-pager-links .pager_ajax_loader").get(0),
						init_function: data.init_function,
						init_parameters: data.init_parameters
					});
					//if the smart feature is active, after the ajaxLink was attached, attach another click event that will fetch the
					//conten of the adiacent links in the pager (if their results are not already cached).
					if (data.smart != 'none'){
						//try to get the data from the next and previous sibling link.
						var href = $(this).next().attr('href');
						var hash_href = hash_link(href, data.container_id);
						if (!pages_cache[hash_href]){
							pages_cache[hash_href] = new Array();
						}
						if (href && !pages_cache[hash_href][data.container_id]){
							$(this).bind('click', function(){
									$.get(href, function(response_data){
										pages_cache[hash_href][data.container_id] = response_data;
									});
							});
						}
						//TO DO: MERGE THIS DUPLICATED CODE.
						var href2 = $(this).prev().attr('href');
						var hash_href2 = hash_link(href2, data.container_id);
						if (!pages_cache[hash_href2]){
							pages_cache[hash_href2] = new Array();
						}
						if (href2 && !pages_cache[hash_href2][data.container_id]){
							$(this).bind('click', function(){
									$.get(href2, function(response_data){
										pages_cache[hash_href2][data.container_id] = response_data;
									});
							});
						}
					}
				});
			});
		}
	}
	
	function show_data_on_page(response_data, data){
		if (data.container){
			$(data.container).html(response_data);
		}
		if (data.init_function){
			if (data.init_parameters){
				data.init_function(data.init_parameters);
			} else {
				data.init_function();
			}
		}
		//hide the loader.
		if (data.loader){
			$(data.loader).hide();
		}
		//scroll to the top of the container div
		//if (data.container && $(data.container).attr('id')){
		//	$.scrollTo($(data.container), 800);
		//}
	}
	
	function pageload(hash){
		//if there is a hash, put the hashed content into the page.
		if (hash){
			// restore ajax loaded state
			if($.browser.msie) {
				// jquery's $.load() function does't work when hash include special characters like aao.
				hash = encodeURIComponent(hash);
			}
			if (pages_cache[hash]){
				for (container_id in pages_cache[hash]){
					if (pages_cache[hash][container_id] && caches_meta[container_id]){
						show_data_on_page(pages_cache[hash][container_id], caches_meta[container_id]);
					}
				}
			}
		} else {
			//TO DO: MERGE THIS DUPLICATED CODE.
			if (pages_cache['initial_value']){
				for (container_id in pages_cache['initial_value']){
					if (pages_cache['initial_value'][container_id] && caches_meta[container_id]){
						show_data_on_page(pages_cache['initial_value'][container_id], caches_meta[container_id]);
					}
				}
			}
		}
	}
	
	$(document).ready(function(){
		$.history.init(pageload);
	});
}